#include "networkmanager.h"
#include "qterminal.h"
#include <QStringList>
#include <QMap>

QStringList NetworkManager::enumDevices()
{
    QStringList devices;

    bool ret = true;
    QString message;
    QTerminal terminal;
    ret = ret && terminal.run("nmcli -f DEVICE device status | awk 'NR>1{print $1}'", &message);
    if (ret)
    {
        QStringList parts = message.split("\n", QString::SkipEmptyParts);
        foreach (const QString &part, parts)
        {
            devices << part;
        }
    }

    return devices;
}

QStringList NetworkManager::enumConnections()
{
    QStringList connections;

    bool ret = true;
    QString message;
    QTerminal terminal;
    ret = ret && terminal.run("nmcli -f NAME connection show | awk -F '\n' 'NR>1{print $1}'", &message);
    if (ret)
    {
        QStringList parts = message.split("\n", QString::SkipEmptyParts);
        foreach (const QString &part, parts)
        {
            connections << part;
        }
    }

    return connections;
}

bool NetworkManager::connectionExists(const QString &name)
{
    return enumConnections().contains(name);
}

NetworkManager::NetworkStatus NetworkManager::connectionStatus(const QString &name)
{
    static const QMap<QString, NetworkStatus> mapper = {
        {"unmanaged", Unmanaged},
        {"unavailable", Unavailable},
        {"connected", Connected},
        {"Disconnected",  Disconnected}
    };

    NetworkStatus status = Unknown;

    bool ret = true;
    QString message;
    QTerminal terminal;
    ret = ret && terminal.run(QString("nmcli -f DEVICE,STATE device | awk -F '\n' 'NR>1{print $1}' | grep '^%1' | sed 's/%1//g' | sed 's/^ *//g'").arg(name), &message);
    if (ret && mapper.contains(message))
    {
        status = mapper[message];
    }

    return status;
}

bool NetworkManager::addConnection(const QString &name, const QString &device, QString *message)
{
    bool ret = true;
    QTerminal terminal;
    ret = ret && terminal.run(QString("nmcli connection add type ethernet ifname '%1' con-name '%2'").arg(device).arg(name), message);
    return ret;
}

bool NetworkManager::removeConnection(const QString &name, QString *message)
{
    bool ret = true;
    QTerminal terminal;
    ret = ret && terminal.run(QString("nmcli connection delete '%1'").arg(name), message);
    return ret;
}

bool NetworkManager::enableConnection(const QString &name, QString *message)
{
    bool ret = true;
    QTerminal terminal;
    ret = ret && terminal.run(QString("nmcli connection up '%1'").arg(name), message);
    return ret;
}

bool NetworkManager::disableConnection(const QString &name, QString *message)
{
    bool ret = true;
    QTerminal terminal;
    ret = ret && terminal.run(QString("nmcli connection down '%1'").arg(name), message);
    return ret;
}

bool NetworkManager::changeConnectionName(const QString &oldName, const QString &newName, QString *message)
{
    bool ret = true;
    QTerminal terminal;
    ret = ret && terminal.run(QString("nmcli connection modify '%1' connection.id '%2'").arg(oldName).arg(newName), message);
    return ret;
}

bool NetworkManager::setIPAddress(const QString &name, const QString &address, QString *message)
{
    bool ret = true;
    QTerminal terminal;
    ret = ret && terminal.run(QString("nmcli connection modify '%1' ipv4.method manual ipv4.address '%2'").arg(name).arg(address), message);
    return ret;
}

bool NetworkManager::setNetmask(const QString &name, const QString &netmask, QString *message)
{
    bool ret = true;
    QTerminal terminal;
    ret = ret && terminal.run(QString("nmcli connection modify '%1' ipv4.method manual ipv4.address %2").arg(name).arg(netmask), message);
    return ret;
}

bool NetworkManager::setGateway(const QString &name, const QString &gateway, QString *message)
{
    bool ret = true;
    QTerminal terminal;
    ret = ret && terminal.run(QString("nmcli connection modify '%1' ipv4.method manual ipv4.gateway '%2'").arg(name).arg(gateway), message);
    return ret;
}

bool NetworkManager::setDNS(const QString &name, const QString &dns, QString *message)
{
    bool ret = true;
    QTerminal terminal;
    ret = ret && terminal.run(QString("nmcli connection modify '%1' ipv4.method manual ipv4.dns '%2'").arg(name).arg(dns), message);
    return ret;
}

bool NetworkManager::setDHCP(const QString &name, QString *message)
{
    bool ret = true;
    QTerminal terminal;
    ret = ret && terminal.run(QString("nmcli connection modify '%1' ipv4.method auto").arg(name), message);
    return ret;
}
